/* Copyright 2018 Canaan Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <camera.h>
#include <dvp.h>
#include <fpioa.h>
#include <lcd.h>
#include <plic.h>
#include <sleep.h>
#include <stdio.h>
#include <string.h>
#include <sysctl.h>
#include <uarths.h>
#include <unistd.h>

uint32_t g_lcd_gram0[38400] __attribute__((aligned(64)));
uint32_t g_lcd_gram1[38400] __attribute__((aligned(64)));

volatile uint8_t g_dvp_finish_flag;
volatile uint8_t g_ram_mux;

static int on_irq_dvp(void *ctx) {
  if (dvp_get_interrupt(DVP_STS_FRAME_FINISH)) {
    /* switch gram */
    dvp_set_display_addr(g_ram_mux ? (uint32_t)g_lcd_gram0
                                   : (uint32_t)g_lcd_gram1);

    dvp_clear_interrupt(DVP_STS_FRAME_FINISH);
    printf("irq\r\n");
    g_dvp_finish_flag = 1;
  } else {
    if (g_dvp_finish_flag == 0) dvp_start_convert();
    dvp_clear_interrupt(DVP_STS_FRAME_START);
  }

  return 0;
}

int main(void) {
  /* Set CPU and dvp clk */
  sysctl_pll_set_freq(SYSCTL_PLL0, 600000000UL);  // DON'T CHANGE THIS!
  sysctl_pll_set_freq(SYSCTL_PLL1, 600000000UL);  // core1
  sysctl_set_spi0_dvp_data(1);
  uarths_init();

  plic_init();

  /* LCD init */
  printf("LCD init\n");
  lcd_init();
  lcd_set_backlight(1);
  lcd_clear(WHITE);
  msleep(100);

  /* DVP init */
  printf("DVP init\n");
  camera_init();

  dvp_set_display_addr((uint32_t)g_lcd_gram0);
  dvp_config_interrupt(DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE, 0);
  dvp_disable_auto();

  /* DVP interrupt config */
  printf("DVP interrupt config\n");
  plic_set_priority(IRQN_DVP_INTERRUPT, 1);
  plic_irq_register(IRQN_DVP_INTERRUPT, on_irq_dvp, NULL);
  plic_irq_enable(IRQN_DVP_INTERRUPT);

  /* enable global interrupt */
  sysctl_enable_irq();
  /* system start */
  printf("system start\n");
  g_ram_mux = 0;
  g_dvp_finish_flag = 0;
  dvp_clear_interrupt(DVP_STS_FRAME_START | DVP_STS_FRAME_FINISH);
  dvp_config_interrupt(DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE, 1);

  while (1) {
    /* ai cal finish*/
    while (g_dvp_finish_flag == 0)
      ;
    g_dvp_finish_flag = 0;
    /* display pic*/
    g_ram_mux ^= 0x01;
    lcd_draw_picture_resized(40, 0, 160, 120,
                             g_ram_mux ? g_lcd_gram0 : g_lcd_gram1);
  }

  return 0;
}
